<?php
/**
 * DolphinGTK - phpGtk framework
 *
 * @package    DolphinGTK
 * @author     Askarov Ruslan
 * @copyright  Askarov Ruslan (c) 2010.
 * @link       http://groups.google.com/group/dolphingtk
 * @license    http://www.opensource.org/licenses/gpl-license.php GPL
 * @version    0.1
 * @since      PHP v.: 5.2.1
 * @subpackage desktop
 * @category   library
 * @filesource
 */

final class Win
{

  // указатель на окно
  public static $_window;

  // отработка клавишь
  public static $accel_group;

  // пока так
  public static $os;

  // указатель на отлов
  private static $_key_ext = true;

  // указатель на обратную функцию,
  // при отлове клавиш
  private static $_key_foo;

  // абс. путь
  private static $_path;

  // timeout
  private static $_timeout = array();

  // наш основной бокс
  private static $_vbox;

  // высота окна
  private static $_height;

  // указатель на статус бар
  private static $_status;

  // для метода prompt
  private static $entry;
  private static $ok=0;
  private static $dialog;
  
  // иконка основного окна
  public static $icon;

  // pid файл, для *nix
  public static $pid_file;

  // длина дисплея
  public static $screen_width;
  
  // высота дисплея
  public static $screen_height;

  // флаг указатель - создано окно или нет
  private static $created_main;

  // указатель на таббер
  private static $win_tabber = null;
  
  // путь до файла, для сохранения положения
  private static $state_save_file;



  /**
   * Метод по умолчанию. Разрешаем использование
   * методов, только как статические.
   *
   * @access public
   * @return void
   */
  public function __construct()
  {
    throw new Exception(
      'Class "Win" used only static methods. And cannot be constructed!'
    );
  }



  /**
   * Метод для проверки наличия метода у окна
   *
   * @access private
   * @param  string $foo
   * @return bool
   */
  private static function ext( $foo = '' )
  {
    if( !self::$_window ) {
      Log::fatal('GtkWindow not initialized!');
    }
    elseif( $foo && method_exists(self::$_window, $foo) ) {
      return true;
    }
    else {
      Log::error('Method "%s" not exists in GtkWindow class!', $foo);
      return false;
    }
  }


  /**
   * Стартовая функция

   *    *
   * @access public
   * @return void
   */
  public static function create()
  {
    if( !class_exists('OS') ) {
      load('os');
    }

    if( !class_exists('Log') ) {
      load('log');
    }

    if( !class_exists('Config') ) {
      load('config');
    }

    // проверка версии php
    if( version_compare(PHP_VERSION, '5.2.0', '<') ) {
      Log::fatal('You must use php 5.2.0 or higher!');
      exit;
    }

    // стандартная проверка.
    if( !class_exists('gtk') ) {
      Log::fatal('Please load the php-gtk2 module in your php.ini!');
    }

    // ОС, под которой запустились
    self::$os = (!self::$os) ? get_os() : self::$os;
    // асболютный путь
    self::$_path = BASE_DIR;

    if( class_exists('GtkWindow') )
    {
      // мультязычность
      if( extension_loaded('gettext') ) {
        if( $_ENV['LANG'] )
        {
          $language = substr($_ENV['LANG'], 0, 2);
          setlocale(LC_ALL, $language);
        }
        ini_set('php-gtk.codepage', 'UTF-8');
        bindtextdomain('messages', BASE_DIR . 'locale');
        textdomain('messages');
        bind_textdomain_codeset('messages', 'UTF-8');
      }
      else {
        Log::error('GetText extension not loaded!');
      }

      // создаем экземпляр окна
      self::$_window = new GtkWindow;

      // корректное завершение
      self::$_window->connect_simple(
        'destroy', array('Gtk', 'main_quit')
      );

      // подгружаем конфиг
      Config::load();

      // сохраним размеры окна
      $screen       = self::$_window->get_screen();
      self::$screen_width  =  $screen->get_width();
      self::$screen_height = $screen->get_height();
      

      if( class_exists('GtkAccelGroup') ) {
        // для отработки клавиш
        self::$accel_group = new GtkAccelGroup();

        if( self::ext('add_accel_group') ):
          // привязываем к окну
          self::$_window->add_accel_group(
            self::$accel_group
          );
        endif;

      } else {
        Log::error('GTK AccelGroup class not loaded!');
        self::$_key_ext = false;
      }

      // внутренняя обёртка
      self::$_vbox = new GtkVBox();

      // отдаем бокс окну
      self::$_window->add(self::$_vbox);

    }
    else
    {
      Log::fatal('GTK win class not loaded!');
      exit;
    }
  }




  /**
   * Задаем заголовок окна
   *
   * @access public
   * @param  string $title
   * @return void
   */
  public static function title( $title )
  {
    if( !empty($title) && self::ext('set_title') ) {
      define('WIN_TITLE', $title);
      self::$_window->set_title($title);
    }
  }




  /**
   * Размер окна
   *
   * @access public
   * @param  int $width
   * @param  int $height
   * @return void
   */
  public static function size( $width, $height )
  {
    if( is_numeric($width) && is_numeric($height) )
    {
      self::$_height = $height;
      if( self::ext('set_size_request') ):
      self::$_window->set_size_request(
        $width, $height
      );
      endif;
    }
  }




  /**
   * Показать или скрыть окно
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function show( $flag = true )
  {
    if( $flag === true ) {
      if( self::ext('show_all') ):
      self::$_window->show_all();
      endif;
    } else {
      if( self::ext('hide_all') ):
      self::$_window->hide_all();
      endif;
    }

  }




  /**
   * Разрешено ли ресайзить окно
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function resizable( $flag )
  {
    if( self::$created_main ) {
      Log::fatal('Win::resizable this param not work after initialization!');
      return false;
    }

    if( is_bool($flag) && self::ext('set_resizable') ) {
      self::$_window->set_resizable($flag);
    }
  }




  /**
   * Позиция окна
   *
   * @access public
   * @param  string $pos
   * @return void
   */
  public static function position( $pos )
  {
    switch( $pos )
    {
      case 'center':
          $p = Gtk::WIN_POS_CENTER;
        break;
      case 'mouse':
          $p = Gtk::WIN_POS_MOUSE;
        break;
      case 'center_always':
          $p = Gtk::WIN_POS_CENTER_ALWAYS;
        break;
      case 'center_on_parent':
          $p = Gtk::WIN_POS_CENTER_ON_PARENT;
        break;
      default:
          $p = Gtk::WIN_POS_NONE;
        break;
    }

    if( self::ext('set_position') ):
      self::$_window->set_position($pos);
    endif;
  }




  /**
   * Иконка окна
   *
   * @access public
   * @param  string $icon
   * @return void
   */
  public static function icon( $icon = false, $gtk_obj = false )
  {
    if( $gtk_obj == false ) {
      self::$icon = $icon;
    }

    $gtk_obj = (!$gtk_obj) ? self::$_window : $gtk_obj;

    if( $icon && file_exists( self::$_path.$icon ) && class_exists('GdkPixbuf') ) {
      $icons = GdkPixbuf::new_from_file(self::$_path.$icon);
    }
    elseif( $icon && get_icon( $icon ) )
    {
      if( self::ext('render_icon') ):
      $icons = $gtk_obj->render_icon(
        get_icon( $icon ), Gtk::ICON_SIZE_DIALOG
      );
      endif;
    }

    if( self::ext('set_icon') && $icons ):
      $gtk_obj->set_icon($icons);
    endif;
  }




  /**
   * Показывать ли обрамление окна
   * точнее кнопки свернуть и т.д.
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function decorated( $flag )
  {
    if( is_bool($flag) && self::ext('set_decorated') )
    {
      self::$_window->set_decorated($flag);
    }
  }


  /**
   * Показывать или нет в пейджере
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function on_pager($flag)
  {
    if( is_bool($flag) && self::ext('set_skip_pager_hint') )
    {
      self::$_window->set_skip_pager_hint($flag);
    }
  }




  /**
   * Показывать ли окно на всех рабочих столах или нет
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function stick( $flag = true )
  {
    if( $flag === true )
    {
      if( self::ext('stick') ):
        self::$_window->stick();
      endif;
    }
    else
    {
      if( self::ext('unstick') ):
        self::$_window->unstick();
      endif;
    }
  }


  /**
   * Сворачиваем и разварачиваем окно
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function state( $flag = true )
  {
    if( $flag === true ) {
      if( self::ext('iconify') ):
      self::$_window->iconify();
      endif;
    } else {
      if( self::ext('deiconify') ):
      self::$_window->deiconify();
      endif;
    }
  }




  /**
   * Восстановить окно / Развернуть на весь экран
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function maximize( $flag = true )
  {
    if( $flag === true ) {
      if( self::ext('maximize') ):
      self::$_window->maximize();
      endif;
    } else {
      if( self::ext('unmaximize') ):
      self::$_window->unmaximize();
      endif;
    }
  }




  /**
   * Показывать ли в панеле задач
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function on_taskbar($flag)
  {
    if( $flag === false && self::ext('set_skip_taskbar_hint') )
    {
      self::$_window->set_skip_taskbar_hint($flag);
    }
  }


  /**
   * Развертка на весь экран или обратно
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function fullscreen( $flag )
  {
    if( $flag == true )
    {
      if( self::ext('fullscreen') ):
        self::$_window->fullscreen();
      endif;
    }
    else
    {
      if( self::ext('unfullscreen') ):
        self::$_window->unfullscreen();
      endif;
    }
  }




  /**
   * Задаем обработчик клавиш
   *
   * @access public
   * @param  string $foo
   * @return void
   */
  public static function on_key( $foo )
  {
    if( self::$_key_ext === true ):
    self::$_key_foo = $foo;
    // для отлова клавишь
    self::$_window->connect(
      'key-press-event',
      array('Win', '_on_key')
    );
    endif;
  }




  public static function _on_key($widget, $event)
  {
    $foo = self::$_key_foo;
    $foo($event->keyval);
  }




  public static function set_modal($flag)
  {
    if( is_bool($flag) && self::ext('set_modal') )
    {
      self::$_window->set_modal($flag);
    }
  }




  public static function border( $num )
  {
    if( is_numeric($num) && self::ext('set_border_width') )
    {
      self::$_window->set_border_width($num);
    }
  }





  /**
   *
   * @param <type> $action
   * @param <type> $foo
   * @param <type> $time
   */
  public static function timeout( $action, $foo, $time = false )
  {
    $time = (!$time) ? 10000 : $time;

    if( is_array($foo) ) {
      $key = implode('',$foo);
      $key = md5($key);
    } else {
      $key = $foo;
    }
    
    if( count($foo) > 2 ) {
      $foo = array_slice($foo,0,2);
    }
    
    if( $action == 'remove' ) {
      if( self::$_timeout[$key] ) {
        Gtk::timeout_remove(self::$_timeout[$key]);
        unset(self::$_timeout[$key]);
      }
    } else {
      self::$_timeout[$key] = Gtk::timeout_add(
        $time, $foo
      );
    }

    unset($time);
  }




  /**
   *
   * @param <type> $x
   * @param <type> $y
   */
  public static function move($x, $y)
  {
    if( self::ext('fullscreen') ):
      self::$_window->move($x, $y);
    endif;
  }




  /**
   *
   * @param string $title
   * @param string $msg
   */
  public static function alert( $title, $msg, $type_icon = false, $icon = false )
  {
    if( !empty($title) && !empty($msg) )
    {
      $dialog = new GtkDialog( $title, null, Gtk::DIALOG_MODAL);

      $icon = (!$icon ) ? self::$icon : $icon;

      if( $icon ) {
        self::icon($icon, $dialog);
      }

      if( $type_icon && file_exists(self::$_path.$type_icon) ) {
        $stock = GtkImage::new_from_file(self::$_path.$type_icon);
      }
      elseif( $type_icon && get_icon( $type_icon ) )
      {
        $stock = GtkImage::new_from_stock(
          get_icon( $type_icon ), Gtk::ICON_SIZE_DIALOG
        );
      }
      else
      {
        $stock = GtkImage::new_from_stock(
          Gtk::STOCK_DIALOG_WARNING,
          Gtk::ICON_SIZE_DIALOG
        );
      }

      $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
      $top_area = $dialog->vbox;

      $top_area->pack_start($hbox = new GtkHBox());

      $hbox->pack_start($stock, 0, 0);
      $hbox->pack_start(new GtkLabel($msg));
      $dialog->add_button(Gtk::STOCK_OK, Gtk::RESPONSE_OK);
      $dialog->set_has_separator(false);
      $dialog->show_all();
      $dialog->run();
      $dialog->destroy();
    }
  }



  /**
   *
   * @param <type> $title
   * @param <type> $msg
   * @return <type>
   */
  static function confirm( $title, $msg, $type_icon = false, $win_icon = false )
  {
    if( !empty($title) && !empty($msg) ):
    $dialog = new GtkDialog(
        $title, NULL, Gtk::DIALOG_MODAL,
        array(
          Gtk::STOCK_NO, Gtk::RESPONSE_NO,
          Gtk::STOCK_YES, Gtk::RESPONSE_YES
        )
    );
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);

    $icon = (!$win_icon) ? self::$icon : $win_icon;
    
    if( $icon ) {
      self::icon($icon, $dialog);
    }

    $dialog->set_has_separator(false);

    $vbox = $dialog->vbox;
    $vbox->add( $hbox = new GtkHBox() );


    if( $type_icon && file_exists( self::$_path.$type_icon ) ) {
      $type_icon = GdkPixbuf::new_from_file(self::$_path.$type_icon);
    }
    elseif( $type_icon && get_icon( $type_icon ) )
    {
      if( self::ext('render_icon') ):
      $type_icon = GtkImage::new_from_stock(
        get_icon( $type_icon ), Gtk::ICON_SIZE_DIALOG
      );
      endif;
    }
    else
    {
      $type_icon = GtkImage::new_from_stock(
        Gtk::STOCK_DIALOG_QUESTION,
        Gtk::ICON_SIZE_DIALOG
      );
    }

    $hbox->pack_start($type_icon);

    $hbox->pack_start( new GtkLabel($msg) );
    $dialog->show_all();

    $result = $dialog->run();

    $dialog->destroy();

    if ($result == Gtk::RESPONSE_NO) {
      return false;
    } elseif ($result == Gtk::RESPONSE_YES) {
      return true;
    } else {
      return false;
    }

    endif;
  }




  public static function menu( $menu )
  {
    if( $menu && is_array($menu) )
    {
      $menubar = new GtkMenuBar();
      self::$_vbox->pack_start($menubar, false, false, 0);

      foreach( $menu as $title => $sub_menu )
      {
        $item[$i] = new GtkMenuItem('_' . $title);

        if( is_array($sub_menu) && is_array($sub_menu[0]) )
        {
          $gmi = Menu::create($sub_menu);

          if( $gmi )
          {
            $item[$i]->set_submenu($gmi);
          }
        }
        elseif( is_array($sub_menu) && !is_array($sub_menu[0]) )
        {
          if( count($sub_menu) == 1 ) {
            $item[$i]->connect('activate', $sub_menu[0] );
          }
          elseif( count($sub_menu) == 2 )
          {
            $item[$i]->connect('activate', $sub_menu );
          }
        }

        $menubar->append($item[$i]);
        $i ++;
      }
    }
  }




  public static function statusbar( $msg )
  {
    if( !empty($msg) )
    {
      self::$_status = new GtkStatusbar();
      $eventbox = new GtkEventBox();
      $eventbox->add(self::$_status);

      //$eventbox->modify_bg(
      //  Gtk::STATE_NORMAL, GdkColor::parse('#ffff00')
      //);

      $context_id = self::$_status->get_context_id('msg1');
      self::$_status->push($context_id, $msg);
      $eventbox->set_size_request(-1, 35);

      self::$_vbox->pack_start($eventbox, false, false, 0);
    }
  }




  public static function statusbar_update( $msg )
  {
    if( !empty( $msg ) ) {
      $context_id = self::$_status->get_context_id('msg1');
      self::$_status->push($context_id, $msg);
    }
  }




  public static function work_space( $statusbar = false )
  {
    $vbox = new GtkVBox();

    if( is_numeric(self::$_height) ) {

      if( $statusbar ) {
        $height = self::$_height - 55;
      } else {
        $height = self::$_height - 25;
      }

      $vbox->set_size_request(0, $height);
    }

    self::$_vbox->pack_start($vbox, false, false, 0);
  }




  /**
   *
   * @param <type> $a
   * @param <type> $b
   * @param <type> $c
   * @param <type> $d
   */
  public static function pack( $a, $b = false, $c = false, $d = 0 )
  {
    self::$_vbox->pack_start( $a, $b, $c, $d );
  }




  public static function bg( $file )
  {
    if( substr($file, 0, 1) == '#' )
    {
      self::$_window->modify_bg(
        Gtk::STATE_NORMAL,
        GdkColor::parse($file)
      );
    }
    elseif( file_exists(self::$_path.$file) )
    {
      $pixbuf = GdkPixbuf::new_from_file(self::$_path.$file);
      list($pixmap, $mask) = $pixbuf->render_pixmap_and_mask(255);
      $style = self::$_window->get_style();
      $style = $style->copy();
      $style->bg_pixmap[Gtk::STATE_NORMAL] = $pixmap;
      self::$_window->set_style($style);
    }
  }



  /**
   * Создаем окно программы
   *
   * @access public
   * @return void
   */
  public static function main()
  {
    self::$created_main = true;
    Gtk::main();
  }




  /**
   * Метод для загрузки модулей
   *
   * @access public
   * @param  string $module
   * @return void
   */
  public static function load( $module )
  {
    if( self::$win_tabber ) {
      self::$win_tabber = null;
    }
    
    $file = self::$_path . 'mod/' . $module . '.php';

    if( file_exists($file) ) {
      include self::$_path . 'mod/' . $module . '.php';

      if( class_exists( $module ) ) {
        $module = ucfirst($module);
        $class = new $module;
          if( method_exists( $class, 'set' ) ) {
            $pack = $class->set();
            self::pack($pack);
          } else {
            Log::fatal('Module "%s::set()" method not exists!', $module);
          }
      } else {
        Log::fatal('Error loading "%s". Please create class "%s"!', $module, $module);
      }
    } else {
      Log::fatal('Module "%s" file do not exists!', $module);
    }
  }




  /**
   * Метод для загрузки модулей в вкладки основного окна
   *
   * @access public
   * @param  string $module
   * @param  string $title
   * @param  string $pos
   * @param  array  $size
   * @return void
   */
  public static function load_tab( $module, $title = '', $pos = 'top', $size = null )
  {
    if( empty($title) )
    {
      static $tab;
      $tab ++;
      $title = "Tab #$tab";
    }
    
    $file = self::$_path . 'mod/' . $module . '.php';

    if( file_exists($file) ) {
      include self::$_path . 'mod/' . $module . '.php';

      if( class_exists( $module ) ) {
        $module = ucfirst($module);
        $class = new $module;
          if( method_exists( $class, 'set' ) ) {
            $pack = $class->set();
            if( self::$win_tabber === null ) {
              if( class_exists( 'Tabber' ) ) {
                self::$win_tabber = new Tabber();
                self::$win_tabber->position($pos);
                self::pack(self::$win_tabber->get());
                if( $size && is_array($size) ) {
                  self::$win_tabber->size($size[0],$size[1]);
                }
              } else {
                Log::fatal("Tabber library not loaded!");
              }
            }
            if( class_exists( 'Tabber' ) ) {
              self::$win_tabber->add($pack, $title);
            }
          } else {
            Log::fatal('Module "%s::set" method not exists!', $module);
          }
      } else {
        Log::fatal('Error loading "%s". Please create class "%s"!', $module, $module);
      }
    } else {
      Log::fatal('Module "%s" file do not exists!', $module);
    }
  }



  public static function prompt( $fields, $width = 200, $bottom = false, $icon = false )
  {
    self::_prompt($fields, $width, $bottom, $icon);

    $new_value = array();
    if( self::$ok === false ) return false;

    for($i=0; $i<count($fields); ++$i) {
      $new_value[] = self::$entry[$i]->get_text();
    }

    return $new_value;
  }



  public static function on_prompt_key($widget, $event, $dialog)
  {
    if( $event->keyval == 65307 )
    {
      $dialog->hide();
    }
  }



  private static function _prompt( $fields, $width, $bottom, $icon )
  {
    $title  = (defined('WIN_TITLE')) ? WIN_TITLE : 'DolphinGTK';
    $bottom = ($bottom) ? $bottom : 'Ok';
    $dialog = new GtkDialog($title, null, Gtk::DIALOG_MODAL|Gtk::DIALOG_NO_SEPARATOR);
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);

    if( !$icon && self::$icon ) {
      self::icon(self::$icon, $dialog);
    } elseif( $icon ) {
      self::icon($icon, $dialog);
    }

    $dialog->connect('key-press-event', array('Win', 'on_prompt_key'), $dialog);
    $table  = new GtkTable();
    self::display_table($table, $fields, $width);
    $dialog->vbox->pack_start($table);

    if( !class_exists('Widgets') ) {
      load('widgets');
    }

    $ok     = Widgets::button($bottom,'ok',array('Win', 'prompt_button', 'ok'));
    $cancel = Widgets::button(i18n('Cancel'),'cancel',array('Win', 'prompt_button', 'cancel'));

    $alignment = new GtkAlignment(0, 0, 0, 0);
    $hbox    = new GtkHBox();
    $hbox->pack_start($ok, 0, 0);
    $hbox->pack_start($cancel, 0, 0);
    $alignment->add($hbox);
    
    $row = count($fields);
    $table->attach($alignment, 1, 2, $row, $row+1,
        Gtk::FILL, Gtk::SHRINK);

    self::$dialog = $dialog;
    $dialog->show_all();
    $dialog->run();
    $dialog->destroy();
  }

  private static function display_table($table, $fields, $width)
  {
    $row = 0;
    foreach ($fields as $label=>$value) {
      $label = new GtkLabel("$label: ");
      self::$entry[$row] = new GtkEntry();
      self::$entry[$row]->set_size_request($width, -1);
      self::$entry[$row]->connect('activate', array('Win', 'prompt_button'), 'ok');
      $alignment = new GtkAlignment(1, .5, 0, 0);
      $alignment->add($label);
      $table->attach($alignment, 0, 1, $row, $row+1);
      $table->attach(self::$entry[$row], 1, 2, $row, $row+1);
      self::$entry[$row]->set_text($value);
      ++$row;
    }
  }

  public static function on_enter($entry, $button) {
    $button->clicked();
  }

  public static function prompt_button($button, $action = 'cancel' ) {
    if( $action == 'ok' ) {
      self::$ok = true;
    } else {
      self::$ok = false;
    }
    self::$dialog->destroy();
  }


  public static function close_terms( $close = false )
  {
    self::$pid_file = (!self::$pid_file) ? OS::get_appdata() . 'run.pid' : self::$pid_file;
    self::$os       = (!self::$os) ? get_os() : self::$os;
    $chdir = OS::get_profile();
    $chdir = (empty($chdir)) ? '/' : $chdir;

    if( self::$os == 'linux' or self::$os == 'macos' )
    {
      if( $close === true ):
      $pid = pcntl_fork();

      if( $pid == 0 )
      {
        #pcntl_signal(SIGUSR1, array('Win','sig_handler'));
        #declare(ticks=1);

        umask(0);
        chdir($chdir);

        define('PID', posix_getpid());

        $f = file_put_contents( self::$pid_file, PID );

        if( !$f ) {
          Win::alert( WIN_TITLE, 'Не удалось сохранить pid в файл!' );
          Log::error( 'Не удалось сохранить pid в файл!' );
        }

        ini_set('max_execution_time', 0);
        ini_set('max_input_time',     0);

        #fclose( STDIN  );
        #fclose( STDOUT );
        #fclose( STDERR );
      }
      elseif( $pid > 0 )
      {
        exit;
      }
      elseif( $pid == -1 )
      {
        Win::alert( WIN_TITLE, 'Не удалось создать процесс.' );
        Log::error( 'Не удалось создать процесс.' );
      }

      endif;
    }
    else
    {
      print "ХЗ как форкается в Win.\nЖдём помощи:)\n";
    }
  }


  public static function sig_handler()
  {}


  public static function close_if_copy()
  {
    self::$pid_file = (!self::$pid_file) ? OS::get_appdata() . 'run.pid' : self::$pid_file;
    self::$os       = (!self::$os) ? get_os() : self::$os;

    if( self::$os == 'linux' or self::$os == 'macos' )
    {
      #Проверяем наличие записи pid
      if ( self::$pid_file && is_readable( self::$pid_file ) ):

      #Получаем запись
      $pid = (int)file_get_contents( self::$pid_file );

      #Проверим наличие процесса
      if ( $pid > 0 && posix_kill($pid, 0) ):
        exit;
      endif;

      #В случае отсутствия, удалим файл
      if ( !unlink(self::$pid_file) ):
        Win::alert(WIN_TITLE, 'Не удалось удалить файл с PID.');
        Log::error('Не удалось удалить файл с PID.');
        exit;
      endif;

      endif;

      unset($pid);
    }
  }



  public static function on_quit( $callback )
  {
    if( !empty($callback) or !is_array($callback) ) {
      self::$_window->connect_simple(
        'delete-event', array('Win','_on_quit'),
        $callback
      );
    }
  }

  public static function _on_quit( $callback )
  {
    if( self::$state_save_file ) {
      self::on_state_event(false);
    }
    
    if( is_array($callback) ) {
      return call_user_func_array($callback);
    }
    else {
      return $callback();
    }
  }


	public static function about( $data, $icon = false )
  {
    $keys = array(
      'program_name'        => 'set_program_name',
      'version'             => 'set_version',
      'authors'             => 'set_authors',
      'documenters'         => 'set_documenters',
      'comments'            => 'set_comments',
      'copyright'           => 'set_copyright',
      'license'             => 'set_license',
      'translator_credits'  => 'set_translator_credits',
      'url_hook'            => 'set_url_hook',
      'website'             => 'set_website',
      'website_label'       => 'set_website_label',
      'email_hook'          => 'set_email_hook',
      'artists'             => 'set_artists',
    );

    if( is_array( $data ) )
    {
      $dialog = new GtkAboutDialog;
      $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
      
      $icon = (!$icon ) ? self::$icon : $icon;
      if( $icon ) {
        self::icon($icon, $dialog);
      }

      foreach( $data as $key => $value )
      {
        if( key_exists($key, $keys) )
        {
          $dialog->$keys[$key]($value);
        }
      }

      $icon = (!$data['logo']) ? self::$icon : $data['logo'];

      if( $icon && file_exists( self::$_path.$icon ) && class_exists('GdkPixbuf') ) {
        $icons = GdkPixbuf::new_from_file(self::$_path.$icon);
      }
      elseif( $icon && get_icon( $icon ) )
      {
        if( self::ext('render_icon') ):
        $icons = $gtk_obj->render_icon(
          get_icon( $icon ), Gtk::ICON_SIZE_DIALOG
        );
        endif;
      }

      if( $icons ) {
      $dialog->set_logo($icons);
      }

      $dialog->run();
      $dialog->hide();
    }

	}



  public static function state_save()
  {
    self::$state_save_file = OS::get_appdata().'state_saved.txt';

    if( file_exists(self::$state_save_file))
    {
      $f = file_get_contents(self::$state_save_file);
      $f = explode(',',$f);
      self::move($f[0],$f[1]);
    }

    self::$_window->connect('window-state-event', array('Win', 'on_state_event'));
    self::$_window->connect_simple_after('delete-event', array('Win', 'on_state_event'), false);
  }


  public static function on_state_event($window)
  {
    if( $window === false) {
      self::_on_state_event(self::$_window);
    } else {
      usleep(500);
      self::_on_state_event($window);
    }
  }


  public static function _on_state_event($window = false )
  {
    $pos = $window->get_position();

    $fp  = @fopen(self::$state_save_file, 'w');
    if( $fp ) {
      flock($fp,2);
      fwrite($fp, "{$pos[0]}, {$pos[1]}");
      flock($fp,3);
      fclose($fp);
    } else {
      print "state not saved\n";
    }
  }



  /**
   * Метод для создания скриншота программы
   *
   * @param string $filename
   * @param string $ext
   */
  public static function screenshot($filename, $ext)
  {
    if( $filename && $ext ) {
      $alloc = self::$_window->allocation;
      $pixbuf = new GdkPixbuf(Gdk::COLORSPACE_RGB, TRUE, 8, $alloc->width, $alloc->height);
      $pixbuf->get_from_drawable(
          self::$_window->window,
          self::$_window->window->get_colormap(),
          $alloc->x,
          $alloc->y,
          0,
          0,
          $alloc->width,
          $alloc->height
      );
      $pixbuf->save($filename, $ext);
    }
  }


  public static function quit()
  {
    if( self::$state_save_file ) {
      self::on_state_event(false);
    }
    Gtk::main_quit();
  }



  /**
   * Метод для создания календаря
   *
   * @access public
   * @param  string $icon
   * @return string
   */
  public static function calendar( $title = '', $icon = '' )
  {
    $dialog = new GtkDialog($title, null, Gtk::DIALOG_MODAL);

    $icon = (!$icon ) ? self::$icon : $icon;

    if( $icon && file_exists( self::$_path.$icon ) && class_exists('GdkPixbuf') ) {
      $icons = GdkPixbuf::new_from_file(self::$_path.$icon);
    }
    elseif( $icon && get_icon( $icon ) )
    {
      $icons = $dialog->render_icon(
        get_icon( $icon ), Gtk::ICON_SIZE_DIALOG
      );
    }

    $dialog->set_icon($icons);
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
    $top_area = $dialog->vbox;
    setlocale(LC_ALL, setlocale(LC_ALL, null));
    $top_area->pack_start($hbox = new GtkHBox());

    $calendar = new GtkCalendar();
    $top_area->pack_start($calendar, 0, 0);

    $dialog->add_button(
      Gtk::STOCK_OK, Gtk::RESPONSE_OK
    );

    $dialog->add_button(
      Gtk::STOCK_CANCEL, Gtk::RESPONSE_CANCEL
    );

    $dialog->set_has_separator(false);
    $dialog->show_all();

    if( $dialog->run() == Gtk::RESPONSE_OK ) {
      $date = $calendar->get_date();
      $selected = $date[0].'-'.(1+$date[1]).'-'.$date[2];
    } else {
      $selected = false;
    }

    $dialog->destroy();

    return $selected;
  }



  public static function get_color( $title = '', $icon = '' )
  {
		$dialog = new GtkColorSelectionDialog($title);
    $icon = (!$icon ) ? self::$icon : $icon;

    if( $icon && file_exists( self::$_path.$icon ) && class_exists('GdkPixbuf') ) {
      $icons = GdkPixbuf::new_from_file(self::$_path.$icon);
    }
    elseif( $icon && get_icon( $icon ) )
    {
      $icons = $dialog->render_icon(
        get_icon( $icon ), Gtk::ICON_SIZE_DIALOG
      );
    }

    $dialog->set_icon($icons);
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);

		$colorsel = $dialog->colorsel;
		$colorsel->set_has_palette(true);

		if( $dialog->run() == Gtk::RESPONSE_OK ) {
      $color = current(
        current(
          next(
            current(
              $colorsel->get_children()
            )->get_children()
          )->get_children()
        )->get_children()
      )->get_text();

		} else {
      $color = false;
    }

		$dialog->destroy();
    return $color;
  }


  public static function get_font( $title = '', $icon = '' )
  {
    $dialog = new GtkFontSelectionDialog($title);
    $icon = (!$icon ) ? self::$icon : $icon;

    if( $icon && file_exists( self::$_path.$icon ) && class_exists('GdkPixbuf') ) {
      $icons = GdkPixbuf::new_from_file(self::$_path.$icon);
    }
    elseif( $icon && get_icon( $icon ) )
    {
      $icons = $dialog->render_icon(
        get_icon( $icon ), Gtk::ICON_SIZE_DIALOG
      );
    }

    $dialog->set_icon($icons);
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);

    $dialog->show_all();
    
    if( $dialog->run() == Gtk::RESPONSE_OK ) {
      $fontname = $dialog->get_font_name();
    } else {
      $fontname = false;
    }

    $dialog->destroy();
    return $fontname;
  }

}
?>